package enet.imitate.common;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 公用 Context 容器
 *
 * @author hubert
 */
public class Context {
    private final Map<Object, Object> mAttrs = new LinkedHashMap<>();
    private final Map<Class, Object> mValues = new LinkedHashMap<>();

    public Context attr(Object key, Object value) {
        mAttrs.put(key, value);
        return this;
    }

    public Context put(Object pValue) {
        if (pValue == null) return this;
        mValues.put(pValue.getClass(), pValue);
        return this;
    }

    public Context attrs(Map pAttrs) {
        this.mAttrs.putAll(pAttrs);
        return this;
    }

    public Object getAttr(Object pKey) {
        return mAttrs.get(pKey);
    }

    public <T> T getAttr(Object pKey, Class<T> pType) {
        return pType.cast(mAttrs.get(pKey));
    }

    public <T> T getAttr(Object pKey, Class<T> pType, T defaultValue) {
        T r = pType.cast(mAttrs.get(pKey));
        return r == null ? defaultValue : r;
    }

    public <T> T getValue(Class<T> pType) {
        if (pType == null) return null;
        Object r = mValues.get(pType);
        if (r != null) return pType.cast(r);
        for (Map.Entry<Class, Object> entry : mValues.entrySet()) {
            if (pType.isAssignableFrom(entry.getKey())) return pType.cast(entry.getValue());
        }
        return null;
    }

    public Boolean getBoolean(Object pKey) {
        return getAttr(pKey, Boolean.class);
    }

    public Boolean getBoolean(Object pKey, Boolean defaultValue) {
        return getAttr(pKey, Boolean.class, defaultValue);
    }

    public Integer getInteger(Object pKey) {
        return getAttr(pKey, Integer.class);
    }

    public Integer getInteger(Object pKey, Integer defaultValue) {
        return getAttr(pKey, Integer.class, defaultValue);
    }

    public Long getLong(Object pKey) {
        return getAttr(pKey, Long.class);
    }

    public Long getLong(Object pKey, Long defaultValue) {
        return getAttr(pKey, Long.class, defaultValue);
    }

    public String getStr(Object pKey) {
        return getAttr(pKey, String.class);
    }

    public String getStr(Object pKey, String defaultValue) {
        return getAttr(pKey, String.class, defaultValue);
    }

    @Override
    public String toString() {
        return "Context [" + mAttrs + "], [" + mValues + "]";
    }
}
